package com.myk.game.gobangchess.rooms;

import com.myk.game.gobangchess.constants.BoardStyleData;
import com.myk.game.gobangchess.constants.WinMode;
import com.myk.game.gobangchess.utils.GridsUtils;
import com.myk.game.gobangchess.rooms.absrooms.AbsOneTwoTwoTwoStepRoom;
import com.myk.game.gobangchess.signs.AroundSign;

import java.util.ArrayList;
import java.util.List;

/**
 * 《王马连星》
 * 黑棋先落1子，然后双方轮流落2子
 * 这2子必须分别落在上一手棋的王、马步位置，或马、王步位置，五连为胜，欠行判负
 */
public class KingHorseStarRoom extends AbsOneTwoTwoTwoStepRoom {

    private static final String MODE_14x14 = "14x14";
    private static final String MODE_16x16 = "16x16";

    private int[] lastPoint;//记录上一子的位置
    private int kingHorseState;//表示目前王马步的状态，0为王马步都能走，1为只能走王步，2为只能走马步

    public KingHorseStarRoom(String roomName) {
        super(roomName, "黑棋先落1子，然后双方轮流落2子,这2子必须分别落在上一子的王、马步位置，每手必走一马一王，五连为胜，欠行判负", "王马连星", BoardStyleData.getGoBangStyle(12, 12), true, true, MODE_14x14, MODE_16x16);
    }

    @Override
    protected void onModeChanged(String mode) {
        if (isNormalMode()){
            this.originGrids = BoardStyleData.getGoBangStyle(12, 12);
            this.curGrids = GridsUtils.copyGrids(originGrids);
        }
        else if (mode.equals(MODE_14x14)){
            this.originGrids = BoardStyleData.getGoBangStyle(14, 14);
            this.curGrids = GridsUtils.copyGrids(originGrids);
        }
        else if (mode.equals(MODE_16x16)){
            this.originGrids = BoardStyleData.getGoBangStyle(16, 16);
            this.curGrids = GridsUtils.copyGrids(originGrids);
        }
    }

    @Override
    public String getRuleText() {
        return "[玩法]\n" +
                "黑棋先落一枚棋子，\n" +
                "随后白黑双方轮流落下两枚棋子。\n" +
                "每回合内落下的两手棋，\n" +
                "必须分别位于上一手棋的：\n" +
                "A.先王步再马步位置\n" +
                "B.先马步再王步位置\n" +
                "[胜负]\n" +
                "获胜条件：五连为胜\n" +
                "失败条件：无棋可走";
    }

    @Override
    public void doRule(int row, int col, int value) {
        if (curGrids[row][col] != 0) {
            return;
        }
        if (step == 0) {
            curGrids[row][col] = value;
            stepAdd();
            firstPoint = new int[]{row, col, value};
            lastPoint = new int[]{row, col, value};
            kingHorseState = 0;
            updateTempPointSigns();
            noticeChangeMove();
        }
        else {
            if (firstPoint == null) {

                boolean horseValid = isValidHorse(row, col);
                boolean kingValid = isValidKing(row, col);
                if (horseValid) {
                    curGrids[row][col] = value;
                    kingHorseState = 1;
                    WinState winState = checkWin(row, col);
                    if (winState != null) {
                        doOver(winState.winMode, winState.winMsg);
                    }
                    else {
                        firstPoint = new int[]{row, col, value};
                        lastPoint = new int[]{row, col, value};
                        updateTempPointSigns();
                        noticeAllRefreshGameInfo();
                    }
                }
                else if (kingValid) {
                    curGrids[row][col] = value;
                    kingHorseState = 2;
                    WinState winState = checkWin(row, col);
                    if (winState != null) {
                        doOver(winState.winMode, winState.winMsg);
                    }
                    else {
                        firstPoint = new int[]{row, col, value};
                        lastPoint = new int[]{row, col, value};
                        updateTempPointSigns();
                        noticeAllRefreshGameInfo();
                    }
                }

            }
            else {
                if (kingHorseState == 1) {
                    boolean kingValid = isValidKing(row, col);
                    if (kingValid) {
                        curGrids[row][col] = value;
                        kingHorseState = 0;
                        secondPoint = new int[]{row, col, value};
                        lastPoint = new int[]{row, col, value};
                        updateTempPointSigns();
                        stepAdd();
                        WinState winState = checkWin(row, col);
                        if (winState != null) {
                            doOver(winState.winMode, winState.winMsg);
                        }
                        else {
                            noticeChangeMove();
                        }
                    }

                }
                else {
                    boolean horseValid = isValidHorse(row, col);
                    if (horseValid) {
                        curGrids[row][col] = value;
                        kingHorseState = 0;
                        secondPoint = new int[]{row, col, value};
                        lastPoint = new int[]{row, col, value};
                        updateTempPointSigns();
                        stepAdd();
                        WinState winState = checkWin(row, col);
                        if (winState != null) {
                            doOver(winState.winMode, winState.winMsg);
                        }
                        else {
                            noticeChangeMove();
                        }
                    }
                }
            }
        }
    }


    @Override
    public String getGameInfo() {
        signList.clear();

        //下一步可以移动的位置
        if (lastPoint != null) {
            if (kingHorseState == 0) {
                beautiHorse();
                beautiKing();
            }
            else if (kingHorseState == 1) {
                beautiKing();
            }
            else {
                beautiHorse();
            }
        }

        signList.addAll(tempPointSigns);
        return super.getGameInfo();
    }

    private void beautiKing() {
        int[][] kingMoves = {{-1, 1}, {-1, 0}, {-1, -1}, {0, 1}, {0, -1}, {1, -1}, {1, 0}, {1, 1}};
        List<Integer> indexes = new ArrayList<Integer>();
        for (int[] move : kingMoves) {
            int nextRow = lastPoint[0] + move[0];
            int nextCol = lastPoint[1] + move[1];
            if (nextRow < curGrids.length && nextCol < curGrids[0].length && nextRow >= 0 && nextCol >= 0) {
                indexes.add(getIndex(nextRow, nextCol));
            }
        }
        signList.add(new AroundSign(indexes, "#440000FF", "#FF0000FF", 1.2f));
    }

    private void beautiHorse() {
        int[][] horseMoves = {{-2, 1}, {-1, 2}, {1, 2}, {2, 1}, {2, -1}, {1, -2}, {-1, -2}, {-2, -1}};
        List<Integer> indexes = new ArrayList<Integer>();
        for (int[] move : horseMoves) {
            int nextRow = lastPoint[0] + move[0];//
            int nextCol = lastPoint[1] + move[1];
            if (nextRow < curGrids.length && nextCol < curGrids[0].length && nextRow >= 0 && nextCol >= 0) {
                indexes.add(getIndex(nextRow, nextCol));
            }
        }
        signList.add(new AroundSign(indexes, "#44FF4500", "#FFFF4500", 1.2f));
    }

    @Override
    protected WinState checkWin(int row, int col) {
        int winValue = 0;
        int[][] dxdy = {{1, 0}, {-1, 1}, {0, 1}, {1, 1}};
        for (int i = 0; i < dxdy.length; i++) {
            int dx = dxdy[i][0], dy = dxdy[i][1];
            int length = getJudgeLength(row, col, dx, dy) + getJudgeLength(row, col, -dx, -dy) - 1;
            if (length >= 5) {
                winValue = (curGrids[row][col] + 1) % 2 + 1;
            }
        }

        boolean gridFull = GridsUtils.getDataCount(curGrids, 0) == 0;

        int[][] horseMoves = {{-2, 1}, {-1, 2}, {1, 2}, {2, 1}, {2, -1}, {1, -2}, {-1, -2}, {-2, -1}};
//        int[][] kingMoves = {{-1, 1}, {1, 1}, {0, 1}, {1, 0}, {1, -1}};
        int[][] kingMoves = {{-1, 1}, {-1, 0}, {-1, -1}, {0, 1}, {0, -1}, {1, -1}, {1, 0}, {1, 1}};

        boolean canMove = false;
        if (kingHorseState == 0) {//判断是否欠行

            for (int[] move : horseMoves) {
                int nextRow = row + move[0];
                int nextCol = col + move[1];
                if (nextRow < curGrids.length && nextCol < curGrids[0].length && nextRow >= 0 && nextCol >= 0)
                    if (curGrids[nextRow][nextCol] == 0) {
                        canMove = true;
                        break;
                    }
            }
            for (int[] move : kingMoves) {
                int nextRow = row + move[0];
                int nextCol = col + move[1];
                if (nextRow < curGrids.length && nextCol < curGrids[0].length && nextRow >= 0 && nextCol >= 0)
                    if (curGrids[nextRow][nextCol] == 0) {
                        canMove = true;
                        break;
                    }
            }

        }
        else if (kingHorseState == 1) {
            for (int[] move : kingMoves) {
                int nextRow = row + move[0];
                int nextCol = col + move[1];
                if (nextRow < curGrids.length && nextCol < curGrids[0].length && nextRow >= 0 && nextCol >= 0)
                    if (curGrids[nextRow][nextCol] == 0) {
                        canMove = true;
                        break;
                    }
            }
        }
        else if (kingHorseState == 2) {
            for (int[] move : horseMoves) {
                int nextRow = row + move[0];
                int nextCol = col + move[1];
                if (nextRow < curGrids.length && nextCol < curGrids[0].length && nextRow >= 0 && nextCol >= 0)
                    if (curGrids[nextRow][nextCol] == 0) {
                        canMove = true;
                        break;
                    }
            }
        }

        if (canMove) {
            if (winValue == 1) {
                return new WinState(WinMode.BLACK_WIN, player_black.getNickNameOrTemp() + "执黑棋战胜" + player_white.getNickNameOrTemp());
            }
            else if (winValue == 2) {
                return new WinState(WinMode.WHITE_WIN, player_white.getNickNameOrTemp() + "执白棋战胜" + player_black.getNickNameOrTemp());

            }
            else if (gridFull) {
                return new WinState(WinMode.BOTH_DRAW, player_black.getNickNameOrTemp() + "-黑棋战平" + player_white.getNickNameOrTemp() + "-白棋");
            }
            else {
                return null;
            }
        }
        else {
            if (cur == 1) {
                if (kingHorseState == 0) {
                    return new WinState(WinMode.BLACK_WIN, player_black.getNickNameOrTemp() + "执黑棋战胜" + player_white.getNickNameOrTemp());
                }
                else {
                    return new WinState(WinMode.WHITE_WIN, player_white.getNickNameOrTemp() + "执白棋战胜" + player_black.getNickNameOrTemp());
                }
            }
            else {
                if (kingHorseState == 0) {
                    return new WinState(WinMode.WHITE_WIN, player_white.getNickNameOrTemp() + "执白棋战胜" + player_black.getNickNameOrTemp());
                }
                else {
                    return new WinState(WinMode.BLACK_WIN, player_black.getNickNameOrTemp() + "执黑棋战胜" + player_white.getNickNameOrTemp());
                }
            }
        }
    }


    private boolean isValidHorse(int row, int col) {
        boolean valid = false;
        if ((Math.abs(lastPoint[0] - row) == 1 && Math.abs(lastPoint[1] - col) == 2) ||
                (Math.abs(lastPoint[0] - row) == 2 && Math.abs(lastPoint[1] - col) == 1)) {
            valid = true;
        }
        return valid;
    }

    private boolean isValidKing(int row, int col) {
        boolean valid = false;
        if ((Math.abs(lastPoint[0] - row) == 1 && Math.abs(lastPoint[1] - col) == 1) ||
                (Math.abs(lastPoint[0] - row) == 1 && Math.abs(lastPoint[1] - col) == 0) ||
                (Math.abs(lastPoint[0] - row) == 0 && Math.abs(lastPoint[1] - col) == 1)) {
            valid = true;
        }
        return valid;
    }

    @Override
    public void resetGrids() {
        step = 0;
        gameTip = "-1";
        curGrids = GridsUtils.copyGrids(originGrids);
        lastPoint = null;
        firstPoint = null;
        secondPoint = null;
        tempPointSigns.clear();
        signList.clear();
    }

}
